#!/usr/bin/env python3
"""
DSL语法迁移脚本 - 改进版
更精确地处理DSL语法替换，避免重复替换和格式问题

使用方法:
python scripts/migrate-dsl-syntax-v2.py [目录路径]
"""

import os
import re
import sys
from pathlib import Path
import argparse
import logging

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class DSLMigratorV2:
    """改进版DSL语法迁移器"""
    
    def __init__(self):
        self.processed_files = []
        self.error_files = []
        
    def migrate_file(self, file_path: Path) -> bool:
        """迁移单个文件"""
        try:
            logger.info(f"正在处理文件: {file_path}")
            
            # 读取文件内容
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            original_content = content
            
            # 应用语法替换
            content = self._apply_replacements(content)
            
            # 如果内容有变化，写回文件
            if content != original_content:
                # 创建备份
                backup_path = file_path.with_suffix(file_path.suffix + '.backup')
                with open(backup_path, 'w', encoding='utf-8') as f:
                    f.write(original_content)
                logger.info(f"已创建备份: {backup_path}")
                
                # 写入新内容
                with open(file_path, 'w', encoding='utf-8') as f:
                    f.write(content)
                
                logger.info(f"✅ 已更新文件: {file_path}")
                self.processed_files.append(str(file_path))
                return True
            else:
                logger.info(f"⏭️  文件无需更新: {file_path}")
                return True
                
        except Exception as e:
            logger.error(f"❌ 处理文件失败 {file_path}: {str(e)}")
            self.error_files.append(str(file_path))
            return False
    
    def _apply_replacements(self, content: str) -> str:
        """应用所有语法替换"""
        
        # 1. 基本字段名称替换 - 只替换顶级字段
        content = re.sub(r'^(\s+)fields:', r'\1attributes:', content, flags=re.MULTILINE)
        content = re.sub(r'^(\s+)relations:', r'\1associations:', content, flags=re.MULTILINE)
        content = re.sub(r'^(\s+)relationships:', r'\1associations:', content, flags=re.MULTILINE)
        content = re.sub(r'^(\s+)emits:', r'\1events:', content, flags=re.MULTILINE)
        
        # 2. 关系类型标准化
        relation_types = [
            ('hasMany', 'one-to-many'),
            ('belongsTo', 'many-to-one'),
            ('hasOne', 'one-to-one'),
            ('belongsToMany', 'many-to-many'),
            ('oneToOne', 'one-to-one'),
            ('oneToMany', 'one-to-many'),
            ('manyToOne', 'many-to-one'),
            ('manyToMany', 'many-to-many'),
        ]
        
        for old_type, new_type in relation_types:
            # 替换 type: 后面的关系类型
            content = re.sub(f'type:\\s*{old_type}', f'type: {new_type}', content)
        
        # 3. 处理验证规则 - 更精确的处理
        content = self._migrate_validation_rules(content)
        
        return content
    
    def _migrate_validation_rules(self, content: str) -> str:
        """迁移验证规则"""
        lines = content.split('\n')
        result_lines = []
        i = 0
        
        while i < len(lines):
            line = lines[i]
            
            # 检查是否是字段定义的开始
            field_match = re.match(r'^(\s+)(\w+):\s*$', line)
            if field_match:
                indent = field_match.group(1)
                field_name = field_match.group(2)
                
                # 处理字段块
                field_lines, next_i = self._process_field_block(lines, i, indent)
                result_lines.extend(field_lines)
                i = next_i
            else:
                result_lines.append(line)
                i += 1
        
        return '\n'.join(result_lines)
    
    def _process_field_block(self, lines, start_i, base_indent):
        """处理单个字段块"""
        result_lines = [lines[start_i]]  # 字段名行
        i = start_i + 1
        
        # 收集字段属性
        field_props = {}
        rules_list = []
        
        while i < len(lines):
            line = lines[i]
            
            # 如果是空行或注释，直接添加
            if not line.strip() or line.strip().startswith('#'):
                result_lines.append(line)
                i += 1
                continue
            
            # 检查缩进，如果不是当前字段的属性，退出
            if line.strip() and not line.startswith(base_indent + '  '):
                break
            
            # 解析属性
            prop_match = re.match(f'^{base_indent}  (\\w+):\\s*(.*)$', line)
            if prop_match:
                prop_name = prop_match.group(1)
                prop_value = prop_match.group(2).strip()
                
                # 处理特殊属性
                if prop_name in ['primary', 'unique', 'required']:
                    if prop_value.lower() == 'true':
                        rules_list.append(prop_name)
                    # 忽略 false 值
                elif prop_name == 'format':
                    rules_list.append(f'{{ format: {prop_value} }}')
                elif prop_name == 'rules':
                    # 处理现有的rules块
                    if prop_value:
                        # 单行rules
                        result_lines.append(line)
                    else:
                        # 多行rules块，需要特殊处理
                        rules_block, next_i = self._process_rules_block(lines, i, base_indent + '  ')
                        result_lines.extend(rules_block)
                        i = next_i
                        continue
                else:
                    # 其他属性直接保留
                    result_lines.append(line)
            else:
                result_lines.append(line)
            
            i += 1
        
        # 如果有收集到的rules，添加到结果中
        if rules_list:
            rules_str = '[' + ', '.join(rules_list) + ']'
            result_lines.insert(-len([l for l in result_lines[1:] if l.strip()]), 
                              f'{base_indent}  rules: {rules_str}')
        
        return result_lines, i
    
    def _process_rules_block(self, lines, start_i, base_indent):
        """处理rules块"""
        result_lines = [lines[start_i]]  # rules: 行
        i = start_i + 1
        
        while i < len(lines):
            line = lines[i]
            
            # 如果是空行或注释，直接添加
            if not line.strip() or line.strip().startswith('#'):
                result_lines.append(line)
                i += 1
                continue
            
            # 检查缩进，如果不是rules的属性，退出
            if line.strip() and not line.startswith(base_indent + '  '):
                break
            
            result_lines.append(line)
            i += 1
        
        return result_lines, i
    
    def migrate_directory(self, directory: Path, pattern: str = "*.yml") -> None:
        """迁移目录下的所有文件"""
        logger.info(f"开始迁移目录: {directory}")
        
        if not directory.exists():
            logger.error(f"目录不存在: {directory}")
            return
        
        # 查找所有匹配的文件
        yaml_files = list(directory.rglob(pattern))
        yaml_files.extend(list(directory.rglob("*.yaml")))
        
        if not yaml_files:
            logger.warning(f"在目录 {directory} 中未找到YAML文件")
            return
        
        logger.info(f"找到 {len(yaml_files)} 个文件需要处理")
        
        # 处理每个文件
        for file_path in yaml_files:
            self.migrate_file(file_path)
    
    def print_summary(self) -> None:
        """打印迁移摘要"""
        print("\n" + "="*60)
        print("DSL语法迁移完成")
        print("="*60)
        print(f"✅ 成功处理文件: {len(self.processed_files)}")
        print(f"❌ 处理失败文件: {len(self.error_files)}")
        
        if self.processed_files:
            print("\n已处理的文件:")
            for file_path in self.processed_files:
                print(f"  - {file_path}")
        
        if self.error_files:
            print("\n处理失败的文件:")
            for file_path in self.error_files:
                print(f"  - {file_path}")
        
        print("\n💡 提示:")
        print("  - 原文件已备份为 .backup 后缀")
        print("  - 请运行测试验证迁移结果")
        print("  - 如有问题可从备份文件恢复")

def main():
    """主函数"""
    parser = argparse.ArgumentParser(description='DSL语法迁移工具 - 改进版')
    parser.add_argument('directory', nargs='?', default='.', 
                       help='要迁移的目录路径 (默认: 当前目录)')
    parser.add_argument('--pattern', default='*.yml', 
                       help='文件匹配模式 (默认: *.yml)')
    
    args = parser.parse_args()
    
    directory = Path(args.directory).resolve()
    
    print("DSL语法迁移工具 - 改进版")
    print("="*40)
    print(f"目标目录: {directory}")
    print(f"文件模式: {args.pattern}")
    print()
    
    # 创建迁移器并执行迁移
    migrator = DSLMigratorV2()
    migrator.migrate_directory(directory, args.pattern)
    migrator.print_summary()

if __name__ == '__main__':
    main()